package sdk.pay.utils.dynamic;

import android.content.Context;
import android.net.Uri;
import android.text.TextUtils;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import sdk.pay.constant.PayConstant;
import sdk.pay.downloadmanager.DownloadRequest;
import sdk.pay.downloadmanager.DownloadStatusListenerV1;
import sdk.pay.downloadmanager.ThinDownloadManager;
import sdk.pay.utils.PayLogUtil;
import sdk.pay.utils.PayPreferenceManager;

import static sdk.pay.constant.PayConstant.SERVER_ADDRESS;

/**
 * Created by Steven on 2016/9/21 0021.
 */

public class PayDownloadUtil {
    private PayPreferenceManager mPayPreferenceManager;
    private String mBasePath;
    private String mVersion;
    private Context mContext;
    private static final int DOWN_THREAD_NUM = 4;

    private PayDownloadUtil() {
    }

    private static class SingleHolder {
        private static final PayDownloadUtil INSTANCE = new PayDownloadUtil();
    }

    public static PayDownloadUtil getInstance() {
        return SingleHolder.INSTANCE;
    }

    void initData(Context context) {
        if (null == mBasePath) {
            mBasePath = context.getFilesDir().getAbsolutePath() + File.separator;
        }
        PayLogUtil.logThird("base path = " + mBasePath);
        if (null == mPayPreferenceManager) {
            mPayPreferenceManager = new PayPreferenceManager(context, PayConstant.CONFIG_FILE_NAME);
        }
        String configVersion = mPayPreferenceManager.getString(PayConstant.CONFIG_SDK_VERSION, "");
        if (TextUtils.isEmpty(configVersion) || !configVersion.equals(PayConstant.VERSION_CODE)) {
            PayLogUtil.logThird("download load reserve jar");
            PayDynamicFileUtil.copyFilesFromAssets(context, context.getFilesDir().getAbsolutePath());
            mPayPreferenceManager.setString(PayConstant.CONFIG_SDK_VERSION, PayConstant.VERSION_CODE);
        }
        File file = new File(context.getFilesDir().getAbsolutePath() + File.separator + PayConstant.PATCH_FILE_RESERVE_NAME);
        if (file.exists()) {
            PayLogUtil.logThird("download load do rename jar");
            PayDynamicFileUtil.reNameFile(context.getFilesDir().getAbsolutePath() + File.separator);
        }
    }

    public void download(Context context) {
        mContext = context;
        initData(context);
        final String url = SERVER_ADDRESS;
        final String fileName = PayConstant.CONFIG_FILE_NAME;
        boolean hasConfig = mPayPreferenceManager.getBoolean(PayConstant.CONFIG_KEY, false);
        PayLogUtil.logThird("download hasConfig = " + hasConfig);
        if (!hasConfig) {
            downloadConfig(url, fileName);
        } else {
            final String version = mPayPreferenceManager.getString(PayConstant.PATCH_VERSION_KEY, "");
            PayLogUtil.logThird("download version = " + version);
            if (!TextUtils.isEmpty(version)) {
                OkHttpClient okHttpClient = new OkHttpClient.Builder().connectTimeout(PayConstant.TIME_OUT, TimeUnit.SECONDS).readTimeout(PayConstant.TIME_OUT, TimeUnit.SECONDS).build();
                okHttpClient.newCall(new Request.Builder().url(PayConstant.VERSION_ADDRESS).build()).enqueue(new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {
                        PayLogUtil.logThird("onFailure reason " + e.getMessage());
                    }

                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        String result = response.body().string();
                        PayLogUtil.logThird("onResponse result = " + result);
                        if (!TextUtils.isEmpty(result)) {
                            if (!result.equals(version)) {
                                PayLogUtil.logThird("download again!!!");
                                downloadConfig(url, fileName);
                            }
                        }
                    }
                });
            } else {
                PayLogUtil.logThird("patch version " + version);
                dateReset();
            }
        }
    }

    private void downloadConfig(String url, String fileName) {
        final String destPath = mBasePath + fileName;
        String sourceUrl = url + fileName;
        Uri uri = Uri.parse(sourceUrl);
        PayLogUtil.logThird("download destPath = " + destPath + " sourceUrl = " + sourceUrl);
        Uri destUri = Uri.parse(destPath);
        DownloadRequest downloadRequest = new DownloadRequest(uri).setDestinationURI(destUri).setPriority(DownloadRequest.Priority.HIGH).setStatusListener(new DownloadStatusListenerV1() {
            @Override
            public void onDownloadComplete(DownloadRequest downloadRequest) {
                PayLogUtil.logThird("downloadConfig onDownloadComplete!!!");
                mPayPreferenceManager.setBoolean(PayConstant.CONFIG_KEY, true);
                getPackageInfoFromXml(destPath);
            }

            @Override
            public void onDownloadFailed(DownloadRequest downloadRequest, int errorCode, String errorMessage) {
                PayLogUtil.logThird("downloadConfig onDownloadFailed errorMessage = !!!" + errorMessage);
            }

            @Override
            public void onProgress(DownloadRequest downloadRequest, long totalBytes, long downloadedBytes, int progress) {
            }
        });
        new ThinDownloadManager(DOWN_THREAD_NUM).add(downloadRequest);
    }

    private void getPackageInfoFromXml(String fileName) {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder;
        try {
            builder = factory.newDocumentBuilder();
            Document document = builder.parse(new File(fileName));
            Element element = document.getDocumentElement();
            Element element1 = (Element) element.getElementsByTagName("Files").item(0);
            Element element2 = (Element) element1.getElementsByTagName("File").item(0);
            mVersion = element2.getAttribute("Ver");
            String nameValue = element2.getAttribute("Name");
            PayLogUtil.logThird(" version = " + mVersion + " nameValue = " + nameValue);
            downloadPatch(SERVER_ADDRESS + nameValue);
        } catch (IOException | ParserConfigurationException | SAXException e) {
            PayLogUtil.logThird("Exception happened " + e.getMessage());
            e.printStackTrace();
        }
    }

    private void downloadPatch(String url) {
        PayLogUtil.logThird("downloadPatch url = " + url);
        final String destPath = mBasePath + PayConstant.PATCH_FILE_RESERVE_NAME;
        Uri uri = Uri.parse(url);
        PayLogUtil.logThird("download destPath = " + destPath + " sourceUrl = " + url);
        Uri destUri = Uri.parse(destPath);
        DownloadRequest downloadRequest = new DownloadRequest(uri).setDestinationURI(destUri).setPriority(DownloadRequest.Priority.HIGH).setStatusListener(new DownloadStatusListenerV1() {
            @Override
            public void onDownloadComplete(DownloadRequest downloadRequest) {
                PayLogUtil.logThird("downloadPatch onDownloadComplete!!!");
                mPayPreferenceManager.setString(PayConstant.PATCH_VERSION_KEY, mVersion);
//                PayDynamicFileUtil.reNameFile(mBasePath);
            }

            @Override
            public void onDownloadFailed(DownloadRequest downloadRequest, int errorCode, String errorMessage) {
                PayLogUtil.logThird("downloadPatch onDownloadFailed errorMessage = !!!" + errorMessage);
            }

            @Override
            public void onProgress(DownloadRequest downloadRequest, long totalBytes, long downloadedBytes, int progress) {
            }
        });
        new ThinDownloadManager(DOWN_THREAD_NUM).add(downloadRequest);
    }

    private PayPreferenceManager getPayPreferenceManager() {
        if (null == mPayPreferenceManager) {
            mPayPreferenceManager = new PayPreferenceManager(mContext, PayConstant.CONFIG_FILE_NAME);
        }
        return mPayPreferenceManager;
    }

    public void dateReset() {
        getPayPreferenceManager().clean();
    }
}